package com.credithc.customers.base.utils;

import org.apache.commons.codec.binary.Base64;
import sun.misc.BASE64Encoder;

import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

/**
 * @author zhukai
 * @date 2018/12/5 10:14
 */
public class RSAUtils {

    private static final String KEY_ALGORITHM = "RSA";
    private static final String PUBLIC_KEY = "RSAPublicKey";
    private static final String PRIVATE_KEY = "RSAPrivateKey";

    /**
     * 获得公钥
     *
     * @param keyMap keyMap
     * @return res
     */
    private static String getPublicKey(Map<String, Object> keyMap) {
        Key key = (Key) keyMap.get(PUBLIC_KEY);
        return encryptBASE64(key.getEncoded());
    }


    /**
     * 获得私钥
     *
     * @param keyMap keyMap
     * @return res
     */
    private static String getPrivateKey(Map<String, Object> keyMap) {
        Key key = (Key) keyMap.get(PRIVATE_KEY);
        return encryptBASE64(key.getEncoded());
    }

    /**
     * 编码返回字符串
     *
     * @param key key
     * @return res
     */
    private static String encryptBASE64(byte[] key) {
        return (new BASE64Encoder()).encodeBuffer(key);
    }

    /*private static byte[] decryptBASE64(String key) throws Exception {
        return (new BASE64Decoder()).decodeBuffer(key);
    }*/

    /**
     * map对象中存放公私钥
     *
     * @return res
     * @throws Exception e
     */
    private static Map<String, Object> initKey() throws Exception {
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(KEY_ALGORITHM);
        keyPairGen.initialize(1024);
        KeyPair keyPair = keyPairGen.generateKeyPair();
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        Map<String, Object> keyMap = new HashMap<>(2);
        keyMap.put(PUBLIC_KEY, publicKey);
        keyMap.put(PRIVATE_KEY, privateKey);
        return keyMap;
    }

    public static String createSign(String str,String privateSorce) throws GeneralSecurityException {
        byte[] data = str.getBytes();
        KeyFactory gen = KeyFactory.getInstance(KEY_ALGORITHM);
        byte[] privateE = Base64.decodeBase64(privateSorce);
        PrivateKey privateKey = gen.generatePrivate(new PKCS8EncodedKeySpec(privateE));
        System.out.println(privateKey);
        //加密
        Signature sign = Signature.getInstance("SHA1withRSA");
        sign.initSign(privateKey);
        sign.update(data);
        byte[] signature = sign.sign();
        return Base64.encodeBase64String(signature);
    }


    public static String createSign(String str) throws GeneralSecurityException {
        byte[] data = str.getBytes();
        KeyFactory gen = KeyFactory.getInstance(KEY_ALGORITHM);
        byte[] privateE = Base64.decodeBase64("MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMpLdWjsgMZzCzB7fRdhFhm5yxYN4fgBLHtK1zbF19mIcKBjkpWlP1SIlwI1NlguqIa3J+zQASSRhMAIJ/ZbdTuHgO5LCC1DwG1OP0cn80I0ppOeGbjpRhhD6qawBhQaoSsUVVhkw9THgXD4qf0HspBPkAWBlE138HahwDJ842EFAgMBAAECgYBNJk4Wv+u0w3dG/DGO0wX8tbDQLmc5kCkItFgzmWxil/hsEs16qNToRldhDi41n0XCauOdGw70hVLdcb7b47FnXvjoA1w5ihjmUe05XYrx6bltTAbkIPp+Oyp5bzwBfxmwYj88Ra9jWGaPSfvERdDHgv3r/YlkwXe2LATGF2onwQJBAOmPNVArtIfHFcxUZY4nlK85ZJCOlqo3W7liyVqv2kZIuwewzMbAyZU40YH6ipmzbF1Z7CL/9enzc5QLB4j0wEkCQQDduz47SKnqTm6Qppy+PC/B55yXYnL6jLTSYnP2QGbny0LMgiVY27j+HA0IKI0a9eNcCs3t1jfwBjvcaUpf8lLdAkBJFuzLKvIy72Vt7Rde1hocf6xt5IFXwT0uFbEHdTKsfgQxku1yYVB0JzTBJUOMd+64g/R2u30ceng34v+3p0gpAkEAuPftZykrzbFWHMdQtIWi1WAwSj0va4GbinHlCMUa0zzF4bKkEydggGLIIEkrxRTgcLT2qvRsP4gDwc/34mhU5QJAW4TZy6PhnoL/eub/mfncEZRfeYUMEjJ2d8hB+a8a2A2nyuEUf0tgzs5WazkOHJABm0IDIVpFrDt2dRKRLFQRFQ==");
        PrivateKey privateKey = gen.generatePrivate(new PKCS8EncodedKeySpec(privateE));
        System.out.println(privateKey);
        //加密
        Signature sign = Signature.getInstance("SHA1withRSA");
        sign.initSign(privateKey);
        sign.update(data);
        byte[] signature = sign.sign();
        return Base64.encodeBase64String(signature);
    }

    public static boolean verifySign(String str, String signature,String publicKeys) throws GeneralSecurityException {
        Signature verifySign = null;
        KeyFactory gen = KeyFactory.getInstance(KEY_ALGORITHM);
        byte[] publicE = Base64.decodeBase64(publicKeys);
        PublicKey publicKey = gen.generatePublic(new X509EncodedKeySpec(publicE));
        System.out.println(publicKey.toString());
        verifySign = Signature.getInstance("SHA1withRSA");
        verifySign.initVerify(publicKey);
        verifySign.update(str.getBytes());
        return verifySign.verify(Base64.decodeBase64(signature));
    }


    public static void main(String[] args) throws GeneralSecurityException {
        //String s = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJQzGlmY9+aHANsuwYINWIc5OWyXMIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJQzGlmY9+aHANsuwYINWIc5OWyXMIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJQzGlmY9+aHANsuwYINWIc5OWyXMIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJQzGlmY9+aHANsuwYINWIc5OWyXMIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJQzGlmY9+aHANsuwYINWIc5OWyXMIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJQzGlmY9+aHANsuwYINWIc5OWyXMIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJQzGlmY9+aHANsuwYINWIc5OWyXMIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJQzGlmY9+aHANsuwYINWIc5OWyXMIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJQzGlmY9+aHANsuwYINWIc5OWyXMIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAJQzGlmY9+aHANsuwYINWIc5OWyX";
        //System.out.println(s);
        Map<String, Object> keyMap;
        try {
            keyMap = initKey();
            String publicKey = getPublicKey(keyMap);
            System.out.println(publicKey);
            test(publicKey);
            String privateKey = getPrivateKey(keyMap);
            System.out.println(privateKey);
            test(privateKey);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static String test(String s){
        String[] split = s.split("\r\n");
        StringBuilder sb = new StringBuilder();
        for(String str : split){
            sb.append(str);
        }
        System.out.println(sb.toString());
        return sb.toString();
    }
}
